package net.stogi.dsper.ui.client.module.user;

import java.util.ArrayList;
import java.util.List;

import net.stogi.common.gwt.dispatch.client.core.ActionManager;
import net.stogi.common.gwt.frame.client.core.EventBus;
import net.stogi.common.gwt.frame.client.mvp.AbstractPresenter;
import net.stogi.common.mvp.core.behavior.Behavior;
import net.stogi.common.mvp.core.behavior.BehaviorWithValue;
import net.stogi.common.mvp.core.model.KeyValues;
import net.stogi.dsper.api.dto.UserProfileDto;
import net.stogi.dsper.ui.shared.module.user.ListUserProfilesAction;
import net.stogi.dsper.ui.shared.module.user.ListUserProfilesResult;

import com.google.gwt.core.client.GWT;
import com.google.gwt.user.client.rpc.AsyncCallback;

class UserProfileListPresenter extends AbstractPresenter {

	private UserProfileDto selectedUserProfileModel;

	private List<UserProfileDto> userProfileListModel;

	private UserProfileListView userProfileListView;

	public UserProfileListPresenter(UserProfileListView userProfileListView, ActionManager actionManager, EventBus eventBus) {
		super(actionManager, eventBus);
		this.userProfileListView = userProfileListView;
		initBehavior();
		initHandlers();
	}

	@Override
	protected void initBehavior() {
		userProfileListView.setAddBehavior(new Behavior() {

			@Override
			public void behave() {
				userProfileListView.block();
				eventBus.fireEvent(new OpenUserProfileEditorEvent(new UserProfileDto()));
			}
		});
		userProfileListView.setCancelBehavior(new Behavior() {

			@Override
			public void behave() {
				userProfileListView.disappear();
				eventBus.fireEvent(new UserProfileListClosedEvent());
			}
		});
		userProfileListView.setEditBehavior(new Behavior() {

			@Override
			public void behave() {
				if (selectedUserProfileModel != null) {
					userProfileListView.block();
					eventBus.fireEvent(new OpenUserProfileEditorEvent(selectedUserProfileModel));
				}
			}
		});
		userProfileListView.setRowSelectedBehavior(new BehaviorWithValue<KeyValues<Long>>() {

			@Override
			public void behave(KeyValues<Long> value) {
				if (value != null) {
					selectedUserProfileModel = internalGetUserProfileFromModel(value.getKey());
				}
			}
		});
	}

	@Override
	protected void initHandlers() {
		eventBus.addHandler(OpenUserProfileListEvent.TYPE, new OpenUserProfileListHandler() {

			@Override
			public void onOpenUserProfileList(OpenUserProfileListEvent event) {
				userProfileListView.appear();
				executeListUserProfiles();
			}
		});
		eventBus.addHandler(UserProfileEditorClosedEvent.TYPE, new UserProfileEditorClosedHandler() {

			@Override
			public void onTagEditorClosed(UserProfileEditorClosedEvent event) {
				if (event.isPersisted()) {
					executeListUserProfiles();
				}
				userProfileListView.unblock();
			}
		});
	}

	private void executeListUserProfiles() {
		actionManager.execute(new ListUserProfilesAction(), new AsyncCallback<ListUserProfilesResult>() {

			@Override
			public void onFailure(Throwable caught) {
				internalHandleException(caught);
				userProfileListView.unblock();
			}

			@Override
			public void onSuccess(ListUserProfilesResult result) {
				userProfileListModel = result.getUserProfiles();
				internalDisplayUserProfiles(userProfileListModel);
			}
		});
	}

	private void internalDisplayUserProfiles(List<UserProfileDto> userProfileList) {
		List<KeyValues<Long>> modelList = new ArrayList<KeyValues<Long>>();
		for (UserProfileDto userProfile : userProfileList) {
			KeyValues<Long> model = new KeyValues<Long>(userProfile.getId());
			model.setValue("name", userProfile.getName());
			modelList.add(model);
		}
		userProfileListView.displayUserProfiles(modelList);
	}

	private UserProfileDto internalGetUserProfileFromModel(Long id) {
		assert id != null : "Parameter 'id' can not be null";
		for (UserProfileDto userProfile : userProfileListModel) {
			if (id.equals(userProfile.getId())) {
				return userProfile;
			}
		}
		return null;
	}

	private void internalHandleException(Throwable caught) {
		// TODO: Add some nice message module in order to show messages from
		// exceptions to user.
		GWT.log("execute*: fail", null);
	}
}
